<?php

namespace IDock\Insurance\CHAC\Request;

use DateTime;
use DateTimeZone;
use Exception;
use IDock\Http\RequestFormat;
use IDock\IDock\IDockEnums;
use IDock\Insurance\CHAC\CHACEnums;
use IDock\Insurance\CHAC\Response\DPremiumInquiryResponse;
use IDock\Insurance\CHAC\Tools\XMLTools;
use IDock\Visitor\NonCar\NonCarProductVisitor;
use IDock\Visitor\Premium\PremiumChargingPileVisitor;
use IDock\Visitor\Premium\PremiumCoverageVisitor;
use IDock\Visitor\Premium\PremiumDeviceVisitor;
use IDock\Visitor\Premium\PremiumInquiryVisitor;

class DPremiumInquiryRequest extends AllCHACRequest
{
    protected $route = 'cxf/policyFeeCountSerivce?wsdl';

    protected $response = DPremiumInquiryResponse::class;

    protected $format = RequestFormat::RAW;

    protected $urlTip = '保费计算';

    /*** @var  PremiumInquiryVisitor $visitor */
    protected $visitor;

    protected $requestData = [];

    /**
     * @return array
     * @throws Exception
     */
    public function generate(): array
    {
        if ($this->requestData) {
            return $this->requestData;
        }
        $data = [
            'Head' => [
                'operatorIp' => '0.0.0.1',
                'requestType' => '00001',
                'userName' => $this->visitor->getExtInfoVisitor()->argc['userName'] ?? '',
                'passWord' => $this->visitor->getExtInfoVisitor()->argc['passWord'] ?? '',
                'queryId' => $this->getRequestId(),
                'partnerCode' => $this->visitor->getExtInfoVisitor()->argc['partnerCode'] ?? '',
            ],
            'BasePart' => [
                'planCode' => '', //
                'cityCode' => $this->visitor->getExtInfoVisitor()->argc['cityCode'] ?? '',
                'renewInd' => '0',
                'orderNumber' => $this->visitor->getExtInfoVisitor()->argc['orderNumber'] ?? '',
            ],
            'ItemMotor' => $this->ItemMotor(),
            'RiskList' => ['Risk'=>$this->riskList()],
            'KindList' => ['Kind'=>$this->coverageList()],
            'CarShipTax' => $this->carShipTax(),
        ];


        //投保人
        $data['RelatedParty'] = $this->applicant();

        //被保人
        $data['RiskRelatedParty'] = $this->insured();

        //设备险
        if ($this->visitor->deviceList) {
            $data['DeviceList'] = ['Device'=>$this->deviceList()];
        }

        //充电桩
        if ($this->visitor->chargingPileVisitorList) {
            $data['ChargingPileList'] = ['ChargingPile'=>$this->chargingPileList()];
        }

        //非车
        if ($this->visitor->nonCarInquiryVisitor->getNonCarList()) {
            /*** @var $single NonCarProductVisitor */
            $single = $this->visitor->nonCarInquiryVisitor->getNonCarList()[0];
            $data['BasePart']['nvhlSuitCode']  = $single->planCode;
        }

        if ($this->visitor->getCiStartData()) {
            $data['BasePart']['planCode'] = '0801';
        }

        if ($this->visitor->getBiStartData()) {
            $data['BasePart']['planCode'] = '0808';
        }

        if ($this->visitor->getBiStartData() and $this->visitor->getCiStartData()) {
            $data['BasePart']['planCode'] = '1363';
        }

        $this->requestData = $data;

        return $data;
    }

    public function soapDataBuild($data): string
    {

        $data = XMLTools::ToXML($data,'arg0');

        return '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pol="http://policyfeecount.provider.app.vhlthirdparty.echannel.ebiz.isoftstone.com/"><soapenv:Header/><soapenv:Body><pol:countFee>'.$data.'</pol:countFee></soapenv:Body></soapenv:Envelope>';
    }

    /**
     * 标的信息
     * @return array
     * @throws Exception
     */
    private function ItemMotor():array
    {

        $owner = $this->visitor->getOwnerVisitor();
        $vehicle = $this->visitor->getVehicleVisitor();

        $data =  [

            //新使用性质
            'useNatureShowNew' => $this->useNature(),
            //车辆所属性质
            'attachNature' => $vehicle->attachNature,

            'licenseNo' => $vehicle->licenseNo,
            'engineNo' => $vehicle->engineNo,
            'modelCode' => $vehicle->vehicleModelCode,
            'frameNo' => $vehicle->vin,
            'carnewoldFlag' => $vehicle->isNewVehicle ? 'N' : 'O',
            'chgOwnerFlag' => ($vehicle->isCiTransfer or $vehicle->isTransfer) ? '01' : '0',
            'licenseTypeCode' => $vehicle->licenseTypeCode,
            'singeinDate' => self::dateFormat($vehicle->firstRegisterDate),
            'enrollDate' => self::dateFormat($vehicle->firstRegisterDate),
            'loanVehicleFlag' => '0',
            'actualValue' => $vehicle->actualValue,
            'seatNum' => $vehicle->vehicleSeat,
            'completeKerbMass' => $vehicle->wholeWeight,
            'fuelTypeCode' => CHACEnums::$energyType[$vehicle->energyTypeCode] ?? '',
            'vehicleCategory' => $vehicle->vehicleStyleCode,
            'energyFlag' => $vehicle->isNewEnergy ? '1' : '0',
            'issueDate' => self::dateFormat($vehicle->issueDate),
            'tonCount' => $vehicle->vehicleTonnage,
            'displacement'=> $vehicle->vehicleExhaust,

            //总行驶里程
            'runMiles' => $vehicle->mileage,

            //'hopeCoefficient' => '',//期望系数


            //车主信息
            'carOwner' => $owner->name,
            'vehicleTypeOfOwner' => CHACEnums::$certificateTypeCode[$owner->certificateTypeCode] ?? '',
            'vehicleOwnerIDNumber' => $owner->certificateNo,
            'ageOfOwner' => $this->getAge($owner->certificateTypeCode,$owner->certificateNo),
            'ownerGender' => $this->getGender($owner->certificateTypeCode,$owner->certificateNo),

            //验车数据
            'carCheckStatus' => CHACEnums::$carCheckCode[$this->visitor->getExtInfoVisitor()->carCheckCode] ?? '',
            'carChecker' => $this->visitor->getExtInfoVisitor()->carChecker,
            'carCheckTime'=> $this->visitor->getExtInfoVisitor()->carCheckDate,
            'carCheckReason' => CHACEnums::$carCheckReasonKind[$this->visitor->getExtInfoVisitor()->carCheckReasonKind] ?? '',

            //新车备案
            //'certificateType' => $this->visitor->vehicleVisitor->carCertificateType,
            //'certificateNo' => $this->visitor->vehicleVisitor->carCertificateNo,
            //'certificateDate' => $this->visitor->vehicleVisitor->carCertificateDate,
        ];
        if ($data['chgOwnerFlag']) {
            $data['transferDate'] = $vehicle->transferDate;
        }

        if ($data['completeKerbMass']) {
            $data['completeKerbMass'] = (string)($data['completeKerbMass'] / 1000);
        }

        if($data['displacement']) {
            $data['displacement'] = $data['displacement'] * 1000;
        }

        //期望折扣系数
        if ($this->visitor->getExtInfoVisitor()->expectedDiscount) {

            $expectedDiscount = $this->visitor->getExtInfoVisitor()->expectedDiscount;

            if ($expectedDiscount < 2) {
                $expectedDiscount *= 100;
            }

            $data['expectDiscount'] = $expectedDiscount;
        }
        //期望系数
        if ($this->visitor->getExtInfoVisitor()->selfPricingFactor) {
            $selfPricingFactor = $this->visitor->getExtInfoVisitor()->selfPricingFactor;

            if ($selfPricingFactor < 2) {
                $selfPricingFactor *= 100;
            }

            $data['hopeCoefficient'] = $selfPricingFactor;
        }

        return $data;
    }

    /**
     * @return array
     * @throws Exception
     */
    private function riskList():array
    {
        $list = [];

        //交强险
        if ($this->visitor->getCiStartData()) {
            $item = [
                'riskCode'  =>'0801',
                'effectFlag' => '0',
                'startDate' => self::dateFormat($this->visitor->getCiStartData()),
                'endDate' => self::dateFormat($this->visitor->getCiEndData())
            ];

            if (date('H', strtotime($item['startDate'])) != '00') {
                $item['effectFlag'] = '1';
            }

            $list[] = $item;
        }

        //商业险
        if ($this->visitor->getBiStartData()) {
            $item = [
                'riskCode'  =>'0808',
                'effectFlag' => '0',
                'startDate' => self::dateFormat($this->visitor->getBiStartData()),
                'endDate' => $this->visitor->getBiEndData()
            ];

            if (date('H', strtotime($item['startDate'])) != '00') {
                $item['effectFlag'] = '1';
                $this->visitor->ciEndData = date('Y-m-d 23:59:59',strtotime($item['endDate']));
                $item['endDate'] = $this->visitor->ciEndData;
            }

            $item['endDate'] = self::dateFormat($item['endDate']);

            $list[] = $item;
        }

        return  $list;
    }

    /**
     * 险种
     * @return array
     */
    private function coverageList():array
    {
        $list = [];

        foreach ($this->visitor->getCoverageVisitorList() as $value) {
            /*** @var $value PremiumCoverageVisitor */

            //交强险
            if ($value->coverageCode == 'C01001') {
                $list[] = [
                    'kindCode' => 'BZ',
                    'riskCode' => '0801',
                    'kindInd' => '1',
                    'mainKindCode' => 'BZ',
                    'quantity' => '0',
                    'relatedInd' => '0',
                    'sumInsured' => '200000.0',
                ];
                continue;
            }

            $item = [
                'kindCode' => CHACEnums::$coverageCode[$value->coverageCode],
                'riskCode' => '0808',
                'sumInsured' => $value->amount,
                'quantity' => '1',
            ];

            $item['mainKindCode'] = CHACEnums::$mainKindCode[$item['kindCode']];

            //主险
            if (in_array($item['kindCode'],['01','02','041','044'])) {
                $item['kindInd'] = '1';
            } else {
                $item['kindInd'] = '2';
            }
            //车损保额
            if ($item['kindCode'] == '01') {
                $value->amount = $this->visitor->vehicleVisitor->negotiatedValue ?: $this->visitor->vehicleVisitor->actualValue;
                $item['sumInsured'] = $value->amount;
            }
            //绝对免赔险
            if (in_array($item['kindCode'],['FA','FB','FD11','FD12'])) {
                $item['quantity'] = $value->deductionRate;
            }
            //服务次数
            if (in_array($item['kindCode'],['S1','S2','S3','S4'])) {
                $item['quantity'] = $value->serviceTimes;
                $item['kindInd'] = '1';
            }
            //修理期间费用补偿险
            if ($item['kindCode'] == '12') {
                $item['unitInsured'] = $value->unitAmount;
                $item['quantity'] = $value->quantity;
            }
            //新增设备险
            if ($item['kindCode'] == '14') {
                $item['sumInsured'] = (string)array_sum(array_column($this->visitor->deviceList,'actualValue'));
            }
            //乘客险保额
            if (in_array($item['kindCode'],['041','044','RD11','RD12','YD11','YD12'])) {

                if ($item['kindCode'] == '044') {
                    $item['unitInsured'] = $value->unitAmount;
                    $item['sumInsured'] = $value->amount;
                    $item['quantity'] = $this->visitor->getVehicleVisitor()->vehicleSeat - 1;
                } else {
                    if(in_array($item['kindCode'],['041','RD11','YD11'])) {
                        $item['unitInsured'] = $value->amount;
                        $item['sumInsured'] = $value->amount;
                    } else {
                        $item['unitInsured'] = $value->amount;
                        $item['sumInsured'] = $value->amount * ($this->visitor->getVehicleVisitor()->vehicleSeat -1);
                        $item['quantity'] = $this->visitor->getVehicleVisitor()->vehicleSeat - 1;
                    }
                }
            }

            $list[] = $item;
        }

        return $list;
    }

    /**
     * 投保人
     * @return array
     * @throws Exception
     */
    private function applicant():array
    {
        $applicant = $this->visitor->getApplicantVisitor();

        $data =  [
            'insuredType' => $applicant->typeCode == 'R1' ? '1': '2',
            'insuredName' => $applicant->name,
            'identifyType' => CHACEnums::$certificateTypeCode[$applicant->certificateTypeCode]??'',
            'identifyNumber' => $applicant->certificateNo,
            'appProvince' => $applicant->provinceCode,
            'appCity' =>$applicant->cityCode,
            'appDistrict' =>$applicant->areaCode,
            'appCompleteAddress' => $applicant->address,
            'terrorNationality' => 'CN',
            'identifyValidDate' => self::dateFormat($applicant->certificateStartDate),
            'identifyValidEndDate' => self::dateFormat($applicant->certificateEndDate),
            'longTerm'  => $applicant->certificateEndDate == '9999-12-31' ? '1' :'0'
        ];

        if ($applicant->typeCode == 'R1') {
            $data['sex'] = $this->getGender($applicant->certificateTypeCode,$applicant->certificateNo);
            $data['birthDate'] = $this->getBirthday($applicant->certificateTypeCode,$applicant->certificateNo);
            $data['insuredAddress'] = $applicant->address;
            $data['postCode'] = $applicant->postcode;
            $data['mobilePhone'] = $applicant->mobile;
            $data['officePhone'] = $applicant->mobile;
            $data['email'] = $applicant->email;
        } else {
            $data['insuredAddress'] = $applicant->address;
            $data['postCode'] = $applicant->postcode;
            $data['officePhone'] = $applicant->mobile;
            $data['mobilePhone'] = $applicant->mobile;
            $data['insuredUnitLeader'] = $applicant->linkManName;
            $data['unitTypeCode'] = CHACEnums::$organizationType[$applicant->organizationType] ?? '';
            $data['unitTypeName'] = CHACEnums::$organizationTypeName[$data['unitTypeCode']] ?? '';

            $data['contactName'] = $applicant->linkManName;
            $data['contactMobile'] = $applicant->mobile;
            $data['contactIdentifyType'] = CHACEnums::$certificateTypeCode[$applicant->linkManCertificateTypeCode]??'';
            $data['contactIdentifyNumber'] = $applicant->linkManCertificateNo;
        }

        return $data;
    }

    /**
     * 被保人
     * @return array
     * @throws Exception
     */
    private function insured():array
    {
        $insured = $this->visitor->getInsuredVisitor();

        $data =  [
            'insuredType' => $insured->typeCode == 'R1' ? '1': '2',
            'insuredName' => $insured->name,
            'identifyType' => CHACEnums::$certificateTypeCode[$insured->certificateTypeCode]??'',
            'identifyNumber' => $insured->certificateNo,
            'insuredProvince' => $insured->provinceCode,
            'insuredCity' =>$insured->cityCode,
            'insuredDistrict' =>$insured->areaCode,
            'insuredCompleteAddress' => $insured->address,
            'terrorNationality' => 'CN',
            'identifyValidDate' => self::dateFormat($insured->certificateStartDate),
            'identifyValidEndDate' => self::dateFormat($insured->certificateEndDate),
            'longTerm'  => $insured->certificateEndDate == '9999-12-31' ? '1' :'0',

            'relationWithHolder' => '0', //被保人与投保人关系
            'carInsuredRelation' => '1', //被保险人与车辆关系
        ];

        if ($this->visitor->getInsuredVisitor()->certificateNo == $this->visitor->getApplicantVisitor()->certificateNo) {
            $data['relationWithHolder'] = '7';
        }

        if ($insured->typeCode == 'R1') {
            $data['insuredSex'] = $this->getGender($insured->certificateTypeCode,$insured->certificateNo);
            $data['insuredBirthDate'] = $this->getBirthday($insured->certificateTypeCode,$insured->certificateNo);
            $data['insuredAddress'] = $insured->address;
            $data['insuredPostCode'] = $insured->postcode;
            $data['insuredMobilePhone'] = $insured->mobile;

        } else {
            $data['insuredAddress'] = $insured->address;
            $data['insuredPostCode'] = $insured->postcode;
            $data['insuredOfficePhone'] = $insured->mobile;
            $data['insuredMobilePhone'] = $insured->mobile;
            $data['insuredUnitLeader'] = $insured->linkManName;
            $data['unitTypeCode'] = CHACEnums::$organizationType[$insured->organizationType] ?? '';
            $data['unitTypeName'] = CHACEnums::$organizationTypeName[$data['unitTypeCode']] ?? '';

            $data['contactName'] = $insured->linkManName;
            $data['contactMobile'] = $insured->mobile;
            $data['carInsuredRelation'] = '1';
            $data['relationWithHolder'] = '0';
        }

        return  $data;
    }

    /**
     * 车船税
     * @return array
     */
    private function carShipTax():array
    {
        $tax = $this->visitor->getCarTaxVisitor();

        $data =  [
            'taxRelifFlag' => CHACEnums::$taxTypeCode[$tax->taxTypeCode] ?? '',
            'paidFreeCertificate' => $tax->taxDocumentNumber,
            'taxCompancyName' => $tax->taxDepartment,
            'relifReason' => CHACEnums::$taxReductionReasonCode[$tax->taxReductionReasonCode] ?? '0',
            'deductionDueType' => $tax->taxReductionCode,
            'freeRate' => $tax->taxFreeRate,
            'lastPaidYear' => date('Y',strtotime('-1 year')),
        ];

        //完税
        if ($tax->taxTypeCode == 'T02') {
            $data['taxProvinceCname'] = $tax->taxPaidAreaCode;
            $data['taxProvinceCode'] = $tax->taxPaidAreaCode;
            $data['taxDocumentDate'] = $tax->taxDocumentDate;
            $data['taxCityCode'] = ''; //税务机关城市代码
            $data['taxCityCname'] = ''; //税务机关城市名称
        }

        return $data;
    }

    /**
     * 设备险
     * @return array
     */
    private function deviceList():array
    {
        $list = [];
        /*** @var PremiumDeviceVisitor $device */
        foreach ($this->visitor->deviceList as $device) {
            $list[] = [
                'deviceName' => $device->deviceName,
                'quantity' => $device->quantity,
                'purchasePrice' => $device->purchasePrice,
                'buyDate' => $device->buyDate,
                'actualValue' => $device->actualValue,
                'deviceType' => '14',
            ];
        }

        return $list;
    }

    /**
     * 充电桩
     * @return array
     */
    private function chargingPileList():array
    {
        $list = [];

        $idx = 1;
        /*** @var PremiumChargingPileVisitor $premiumChargingPileVisitor */
        foreach ($this->visitor->chargingPileVisitorList as $premiumChargingPileVisitor) {

            //责任保险保额
            if ($premiumChargingPileVisitor->liabilityAmount) {
                $list[] = [
                    'serialNo' => (string)$idx,
                    'kindCode' => 'UB',
                    'type' => $premiumChargingPileVisitor->chargingPileType,
                    'code' => $premiumChargingPileVisitor->chargingPileCode,
                    'address' => $premiumChargingPileVisitor->chargingPileAddress,
                    'addressType' => CHACEnums::$chargingPileAddressType[$premiumChargingPileVisitor->chargingPileAddressType],
                    'chargePileType' => CHACEnums::$chargingPileKind[$premiumChargingPileVisitor->chargingPileKind],
                    'limitYear' => CHACEnums::$chargingPileYearLimit[$premiumChargingPileVisitor->chargingPileYearLimit],
                    'amount' => $premiumChargingPileVisitor->liabilityAmount
                ];
            }

            //损失保险保额
            if ($premiumChargingPileVisitor->lossAmount) {
                $list[] = [
                    'serialNo' => (string)$idx,
                    'kindCode' => 'UA',
                    'type' => $premiumChargingPileVisitor->chargingPileType,
                    'code' => $premiumChargingPileVisitor->chargingPileCode,
                    'address' => $premiumChargingPileVisitor->chargingPileAddress,
                    'addressType' => CHACEnums::$chargingPileAddressType[$premiumChargingPileVisitor->chargingPileAddressType],
                    'chargePileType' => CHACEnums::$chargingPileKind[$premiumChargingPileVisitor->chargingPileKind],
                    'limitYear' => CHACEnums::$chargingPileYearLimit[$premiumChargingPileVisitor->chargingPileYearLimit],
                    'amount' => $premiumChargingPileVisitor->lossAmount
                ];
            }
        }

        return $list;
    }


    //------------------

    /**
     * 年龄计算
     * @param $type
     * @param $idCard
     * @return int|string
     */
    private function getAge($type,$idCard)
    {
        if ($type != '01') {
            return '0';
        }

        $birthdate = substr($idCard, 6, 8);
        $birthYear = substr($birthdate, 0, 4);
        $birthMonth = substr($birthdate, 4, 2);
        $birthDay = substr($birthdate, 6, 2);

        $currentYear = date('Y');
        $currentMonth = date('m');
        $currentDay = date('d');

        $age = $currentYear - $birthYear;
        if ($currentMonth < $birthMonth || ($currentMonth == $birthMonth && $currentDay < $birthDay)) {
            $age--; // 未过生日，年龄减一
        }

        return $age;
    }

    /**
     * 性别判定
     * @param $type
     * @param $idCard
     * @return string
     */
    private function getGender($type,$idCard): string
    {

        if ($type != '01' or strlen($idCard) != 18) {
            return '1';
        }

        $gender = intval(substr($idCard,16,1)) % 2;

        return $gender ? '2' : '1';
    }
    /**
     * 生日
     */
    public function getBirthday($type,$idCard): string
    {
        if ($type != '01' or strlen($idCard) != 18) {
            return '';
        }

        return substr($idCard,6,4).'-'.substr($idCard,10,2).'-'.substr($idCard,12,2).'T23:00:00+08:00';
    }

    /**
     * 新使用性质
     * @return string
     */
    private function useNature(): string
    {
        $useNatureCode = $this->visitor->getVehicleVisitor()->useNatureCode;
        $causeType = $this->visitor->getVehicleVisitor()->causeType;
        $carKindCode = $this->visitor->getVehicleVisitor()->carKindCode;

        $useNature = CHACEnums::$causeType[$causeType];

        if ($carKindCode == '200' or $carKindCode == '210') {
            if ($useNatureCode == '01') {
                return '12';
            }
        }

        if ($useNature) {
            return $useNature;
        }
        //机关自用
        if ($causeType == '002') {
            return '11';
        }
        //企业自用
        if ($causeType == '003') {
            return '10';
        }

        return '';
    }

    /**
     * 时间格式
     * @param string $dateTimeString
     * @return string
     * @throws Exception
     */
    private function dateFormat(string $dateTimeString) :string
    {
        if (!$dateTimeString) {
            return '';
        }

        $dateTime = new DateTime($dateTimeString);

        // 设置时区为 +08:00
        $timeZone = new DateTimeZone('+08:00');
        $dateTime->setTimezone($timeZone);

        // 格式化日期时间为指定的格式
        return $dateTime->format('Y-m-d\TH:i:sP');
    }
}
